home *** CD-ROM | disk | FTP | other *** search
- /* pl-os.c,v 1.45 1994/04/11 08:37:37 jan Exp
-
- Copyright (c) 1990 Jan Wielemaker. All rights reserved.
- See ../LICENCE to find out about your rights.
- jan@swi.psy.uva.nl
-
- Purpose: Operating System Dependencies
- */
-
- /* Modified (M) 1993 Dave Sherratt */
-
- /*#define O_DEBUG 1*/
-
- #define unix 1
-
- #if __TOS__
- #include <tos.h> /* before pl-os.h due to Fopen, ... */
- #endif
- #if OS2 && EMX
- #include <os2.h> /* this has to appear before pl-incl.h */
- #endif
-
- #include <math.h> /* avoid abs() problem with msvc++ */
- #include "pl-incl.h"
- #include "pl-ctype.h"
-
- #if HAVE_SYS_STAT_H
- #include <sys/stat.h>
- #endif
- #if !O_XOS
- #define statfunc stat
- #endif
- #if HAVE_PWD_H
- #include <pwd.h>
- #endif
- #if HAVE_VFORK_H
- #include <vfork.h>
- #endif
- #ifdef HAVE_UNISTD_H
- #include <unistd.h>
- #endif
- #ifdef HAVE_SYS_PARAM_H
- #include <sys/param.h>
- #endif
- #ifdef HAVE_SYS_FILE_H
- #include <sys/file.h>
- #endif
-
- #include <fcntl.h>
- #ifndef __WATCOMC__ /* appears a conflict */
- #include <errno.h>
- #endif
-
- #if defined(__WATCOMC__)
- #include <io.h>
- #include <dos.h>
- #endif
-
- #if OS2 && EMX
- static real initial_time;
- #endif /* OS2 */
-
- forwards void initExpand(void);
- forwards void initRandom(void);
- forwards void initEnviron(void);
- forwards long Time(void);
- static void RemoveTemporaryFiles(void);
-
- #ifndef DEFAULT_PATH
- #define DEFAULT_PATH "/bin:/usr/bin"
- #endif
-
- /*******************************
- * GLOBALS *
- *******************************/
- #ifdef HAVE_CLOCK
- long clock_wait_ticks;
- #endif
-
- /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- This module is a contraction of functions that used to be all over the
- place. together with pl-os.h (included by pl-incl.h) this file
- should define a basic layer around the OS, on which the rest of
- SWI-Prolog is based. SWI-Prolog has been developed on SUN, running
- SunOs 3.4 and later 4.0.
-
- Unfortunately some OS's simply do not offer an equivalent to SUN os
- features. In most cases part of the functionality of the system will
- have to be dropped. See the header of pl-incl.h for details.
- - - - - - - - - - - - - - - - - */
-
- /********************************
- * INITIALISATION *
- *********************************/
-
- /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- bool initOs()
-
- Initialise the OS dependant functions.
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
-
- bool
- initOs(void)
- { DEBUG(1, Sdprintf("OS:initExpand() ...\n"));
- initExpand();
- DEBUG(1, Sdprintf("OS:initRandom() ...\n"));
- initRandom();
- DEBUG(1, Sdprintf("OS:initEnviron() ...\n"));
- initEnviron();
-
- #ifdef __WIN32__
- if ( iswin32s() )
- set(&features, DOS_FILE_NAMES_FEATURE);
- else
- set(&features, FILE_CASE_PRESERVING_FEATURE);
- #else
- set(&features, FILE_CASE_FEATURE);
- set(&features, FILE_CASE_PRESERVING_FEATURE);
- #endif
-
- #ifdef HAVE_CLOCK
- clock_wait_ticks = 0L;
- #endif
-
- #if OS2
- { DATETIME i;
- DosGetDateTime((PDATETIME)&i);
- initial_time = (i.hours * 3600.0)
- + (i.minutes * 60.0)
- + i.seconds
- + (i.hundredths / 100.0);
- }
- #endif /* OS2 */
-
- DEBUG(1, Sdprintf("OS:done\n"));
-
- succeed;
- }
-
- typedef void (*halt_function)(int, Void);
-
- struct on_halt
- { halt_function function;
- Void argument;
- OnHalt next;
- };
-
-
- void
- PL_on_halt(halt_function f, Void arg)
- { if ( !GD->os.halting )
- { OnHalt h = allocHeap(sizeof(struct on_halt));
-
- h->function = f;
- h->argument = arg;
- startCritical;
- h->next = GD->os.on_halt_list;
- GD->os.on_halt_list = h;
- endCritical;
- }
- }
-
-
- volatile void
- Halt(int rval)
- { OnHalt h;
- extern int Output;
-
- pl_notrace(); /* avoid recursive tracing */
- Output = 1; /* reset output stream to user */
-
- if ( !GD->os.halting )
- { GD->os.halting++; /* avoid recursion */
-
- for(h = GD->os.on_halt_list; h; h = h->next)
- (*h->function)(rval, h->argument);
-
- if ( GD->initialised )
- { fid_t cid = PL_open_foreign_frame();
- predicate_t proc = PL_predicate("$run_at_halt", 0, "system");
- PL_call_predicate(MODULE_system, FALSE, proc, 0);
- PL_discard_foreign_frame(cid);
- }
-
- #if defined(__WINDOWS__) || defined(__WIN32__)
- if ( rval != 0 )
- PlMessage("Exit status is %d", rval);
- #endif
-
- qlfCleanup(); /* remove errornous .qlf files */
- dieIO();
-
- if ( GD->initialised )
- { fid_t cid = PL_open_foreign_frame();
- predicate_t proc = PL_predicate("unload_all_foreign_libraries", 0,
- "shlib");
- if ( isDefinedProcedure(proc) )
- PL_call_predicate(MODULE_system, FALSE, proc, 0);
- PL_discard_foreign_frame(cid);
- }
-
- RemoveTemporaryFiles();
- }
-
- exit(rval);
- /*NOTREACHED*/
- }
-
- /********************************
- * OS ERRORS *
- *********************************/
-
- /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- char *OsError()
- Return a char *, holding a description of the last OS call error.
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
-
- char *
- OsError(void)
- {
- #ifdef HAVE_STRERROR
- #ifdef __WIN32__
- return strerror(_xos_errno());
- #else
- return strerror(errno);
- #endif
- #else /*HAVE_STRERROR*/
- static char errmsg[64];
-
- #if unix
- extern int sys_nerr;
- #if !EMX
- extern char *sys_errlist[];
- #endif
- extern int errno;
-
- if ( errno < sys_nerr )
- return sys_errlist[errno];
- #endif
-
- Ssprintf(errmsg, "Unknown Error (%d)", errno);
- return errmsg;
- #endif /*HAVE_STRERROR*/
- }
-
- /********************************
- * PROCESS CHARACTERISTICS *
- *********************************/
-
- /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- real CpuTime()
-
- Returns a floating point number, representing the amount of (user)
- CPU-seconds used by the process Prolog is in. For systems that do
- not allow you to obtain this information you may wish to return
- elapsed time since Prolog was started, as this function is used to
- by consult/1 and time/1 to determine the amount of CPU time used to
- consult a file or to execute a query.
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
-
- #ifndef __WIN32__ /* defined in pl-nt.c */
-
- #ifdef HAVE_TIMES
- #include <sys/times.h>
-
- #if defined(_SC_CLK_TCK)
- #define Hz ((int)sysconf(_SC_CLK_TCK))
- #else
- #ifdef HZ
- # define Hz HZ
- #else
- # define Hz 60 /* if nothing better: guess */
- #endif
- #endif /*_SC_CLK_TCK*/
- #endif /*HAVE_TIMES*/
-
-
- real
- CpuTime(void)
- {
- #ifdef HAVE_TIMES
- struct tms t;
- static int MTOK_got_hz = FALSE;
- static real MTOK_hz;
-
- if ( !MTOK_got_hz )
- { MTOK_hz = (real) Hz;
- MTOK_got_hz++;
- }
- times(&t);
-
- return (real) t.tms_utime / MTOK_hz;
- #endif
-
- #if OS2 && EMX
- DATETIME i;
-
- DosGetDateTime((PDATETIME)&i);
- return (((i.hours * 3600)
- + (i.minutes * 60)
- + i.seconds
- + (i.hundredths / 100.0)) - initial_time);
- #endif
-
- #ifdef HAVE_CLOCK
- return (real) (clock() - clock_wait_ticks) / (real) CLOCKS_PER_SEC;
- #endif
- }
-
- #endif /*__WIN32__*/
-
- #ifdef HAVE_CLOCK
- void
- PL_clock_wait_ticks(long waited)
- { clock_wait_ticks += waited;
- }
- #endif
-
- /********************************
- * MEMORY MANAGEMENT *
- *********************************/
-
- /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- long *Allocate(n)
- long n;
-
- Allocate a memory area of `n' bytes from the operating system. `n'
- is a long as we need to allocate one uniform array of longs for both
- the local stack and global stack, which implies it should be
- possible to allocate at least a few hundred Kbytes. If you cannot
- implement this function you are in deep trouble. You either can
- decide to redesign large part of the data representation, or forget
- about SWI-Prolog. Memory is never returned to the system. As it
- would only concern small areas, all over SWI-Prolog's memory no
- currently available operating system (I'm aware of) will be able to
- handle it anyway. THE RETURN VALUE SHOULD BE ROUNDED TO BE A VALID
- POINTER FOR LONGS AND STRUCTURES AND AT LEAST A MULTIPLE OF 4.
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
-
- Void
- Allocate(long n)
- { Void mem = malloc(n);
-
- return (Void) mem;
- }
-
-
- /********************************
- * STRING MANIPULATION *
- ********************************/
-
- /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- The builtin strcmp() of SunOs is broken on some machines ...
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
-
- #if sun
- int
- strcmp(const char *s1, const char *s2)
- { while(*s1 && *s1 == *s2)
- s1++, s2++;
-
- return *(const unsigned char *)s1 -
- *(const unsigned char *)s2;
- }
- #endif
-
-
- /********************************
- * ARITHMETIC *
- *********************************/
-
- /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- long Random()
-
- Return a random number. Used for arithmetic only.
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
-
- static void
- initRandom(void)
- { long init = Time();
- #ifdef HAVE_SRANDOM
- srandom(init);
- #else
- #ifdef HAVE_SRAND
- srand(init);
- #endif
- #endif
- }
-
- long
- Random(void)
- {
- #ifdef HAVE_RANDOM
- return random();
- #else
- long l = rand(); /* 0<n<2^15-1 */
-
- l ^= rand()<<10;
- l ^= rand()<<20;
-
- return l & (~PLMININT);
- #endif
- }
-
- /********************************
- * FILES *
- *********************************/
-
- /* (Everything you always wanted to know about files ...) */
-
- /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- Generation and administration of temporary files. Currently only used
- by the foreign language linker. It might be useful to make a predicate
- available to the Prolog user based on these functions. These functions
- are in this module as non-UNIX OS probably don't have getpid() or put
- temporaries on /tmp.
-
- atom_t TemporaryFile(const char *id)
-
- The return value of this call is an atom, whose string represents
- the path name of a unique file that can be used as temporary file.
- `id' is a char * that can be used to make it easier to identify the
- file as a specific kind of SWI-Prolog intermediate file.
-
- void RemoveTemporaryFiles()
-
- Remove all temporary files. This function should be aware of the
- fact that some of the file names generated by TemporaryFile() might
- not be created at all, or might already have been deleted.
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
-
- struct tempfile
- { atom_t name;
- TempFile next;
- }; /* chain of temporary files */
-
- #define tmpfile_head (GD->os._tmpfile_head)
- #define tmpfile_tail (GD->os._tmpfile_tail)
-
- #ifndef DEFTMPDIR
- #ifdef __WIN32__
- #define DEFTMPDIR "c:/tmp"
- #else
- #define DEFTMPDIR "/tmp"
- #endif
- #endif
-
- atom_t
- TemporaryFile(const char *id)
- { char temp[MAXPATHLEN];
- TempFile tf = allocHeap(sizeof(struct tempfile));
- char envbuf[MAXPATHLEN];
- char *tmpdir;
-
- if ( !((tmpdir = getenv3("TEMP", envbuf, sizeof(envbuf))) ||
- (tmpdir = getenv3("TMP", envbuf, sizeof(envbuf)))) )
- tmpdir = DEFTMPDIR;
-
- #if unix
- { static int MTOK_temp_counter = 0;
-
- Ssprintf(temp, "%s/pl_%s_%d_%d",
- tmpdir, id, (int) getpid(), MTOK_temp_counter++);
- }
- #endif
-
- #ifdef __WIN32__
- { char *tmp;
- static int temp_counter = 0;
-
- #ifdef __LCC__
- if ( (tmp = tmpnam(NULL)) )
- #else
- if ( (tmp = _tempnam(tmpdir, id)) )
- #endif
- { PrologPath(tmp, temp);
- } else
- Ssprintf(temp, "%s/pl_%s_%d", tmpdir, id, temp_counter++);
- }
- #endif
-
- #if EMX
- static int temp_counter = 0;
- char *foo;
-
- if ( (foo = tempnam(".", (const char *)id)) )
- { strcpy(temp, foo);
- free(foo);
- } else
- Ssprintf(temp, "pl_%s_%d_%d", id, getpid(), temp_counter++);
- #endif
-
- #if tos
- tmpnam(temp);
- #endif
-
- tf->name = lookupAtom(temp);
- tf->next = NULL;
-
- startCritical;
- if ( !tmpfile_tail )
- { tmpfile_head = tmpfile_tail = tf;
- } else
- { tmpfile_tail->next = tf;
- tmpfile_tail = tf;
- }
- endCritical;
-
- return tf->name;
- }
-
- static void
- RemoveTemporaryFiles()
- { TempFile tf, tf2;
-
- startCritical;
- for(tf = tmpfile_head; tf; tf = tf2)
- { RemoveFile(stringAtom(tf->name));
- tf2 = tf->next;
- freeHeap(tf, sizeof(struct tempfile));
- }
-
- tmpfile_head = tmpfile_tail = NULL;
- endCritical;
- }
-
- /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- Fortunately most C-compilers are sold with a library that defines
- Unix-style access to the file system. The standard functions go via
- macros to deal with 16-bit machines, but are not defined as functions
- here. Some more specific things SWI-Prolog wants to know about files
- are defined here:
-
- int getdtablesize()
-
- SWI-Prolog assumes it can refer to open i/o streams via read() and
- write() by small integers, returned by open(). These integers should
- be in the range [0, ..., getdtablesize()). If your system does not
- do this you better redefine the Open(), Read() and Write() macros so
- they do meet this requirement. Prolog allocates a table of
- structures with getdtablesize() entries.
-
- long LastModifiedFile(path)
- char *path;
-
- Returns the last time `path' has been modified. Used by the source
- file administration to implement make/0.
-
- bool ExistsFile(path)
- char *path;
-
- Succeeds if `path' refers to the pathname of a regular file (not a
- directory).
-
- bool AccessFile(path, mode)
- char *path;
- int mode;
-
- Succeeds if `path' is the pathname of an existing file and it can
- be accessed in any of the inclusive or constructed argument `mode'.
-
- bool ExistsDirectory(path)
- char *path;
-
- Succeeds if `path' refers to the pathname of a directory.
-
- bool RemoveFile(path)
- char *path;
-
- Removes a (regular) file from the file system. Returns TRUE if
- succesful FALSE otherwise.
-
- bool RenameFile(old, new)
- char *old, *new;
-
- Rename file from name `old' to name `new'. If new already exists, it is
- deleted. Returns TRUE if succesful, FALSE otherwise.
-
- bool OpenStream(stream)
- int stream;
-
- Succeeds if `stream' refers to an open i/o stream.
-
- bool MarkExecutable(path)
- char *path;
-
- Mark `path' as an executable program. Used by the intermediate code
- compiler and the creation of stand-alone executables.
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
-
- #ifndef HAVE_GETDTABLESIZE
- int
- getdtablesize()
- {
- #ifdef OPEN_MAX
- return OPEN_MAX;
- #else
- #ifdef _SC_OPEN_MAX /* POSIX, USG */
- return sysconf(_SC_OPEN_MAX);
- #else
- #ifdef HAVE_GETRLIMIT
- #ifdef HAVE_SYS_RESOURCE_H
- #include <sys/resource.h>
- #endif
- #ifdef RLIMIT_NOFILE
- { struct rlimit rlp;
- getrlimit(RLIMIT_NOFILE,&rlp);
- return (rlp.rlim_cur);
- }
- #endif /*RLIMIT_NOFILE*/
- #endif /*HAVE_GETRLIMIT*/
- #endif /*_SC_OPEN_MAX*/
- #endif /*OPEN_MAX*/
- }
- #endif /*HAVE_GETDTABLESIZE*/
-
- /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- Size of a VM page of memory. Most BSD machines have this function. If not,
- here are several alternatives ...
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
-
- #ifndef HAVE_GETPAGESIZE
- #ifdef _SC_PAGESIZE
- int
- getpagesize()
- { return sysconf(_SC_PAGESIZE);
- }
- #else /*_SC_PAGESIZE*/
-
- #if hpux
- #include <a.out.h>
- int
- getpagesize()
- {
- #ifdef EXEC_PAGESIZE
- return EXEC_PAGESIZE;
- #else
- return 4096; /* not that important */
- #endif
- }
- #endif /*hpux*/
- #endif /*_SC_PAGESIZE*/
- #endif /*HAVE_GETPAGESIZE*/
-
- #if O_HPFS
-
- /* Conversion rules Prolog <-> OS/2 (using HPFS)
- / <-> \
- /x:/ <-> x:\ (embedded drive letter)
- No length restrictions up to MAXPATHLEN, no case conversions.
- */
-
- char *
- PrologPath(char *ospath, char *path)
- { char *s = ospath, *p = path;
- int limit = MAXPATHLEN-1;
-
- if (isLetter(s[0]) && s[1] == ':')
- { *p++ = '/';
- *p++ = *s++;
- *p++ = *s++;
- limit -= 3;
- }
- for(; *s && limit; s++, p++, limit--)
- *p = (*s == '\\' ? '/' : makeLower(*s));
- *p = EOS;
-
- return path;
- }
-
-
- char *
- OsPath(const char *plpath, char *path)
- { const char *s = plpath, *p = path;
- int limit = MAXPATHLEN-1;
-
- if ( s[0] == '/' && isLetter(s[1]) && s[2] == ':') /* embedded drive letter*/
- { s++;
- *p++ = *s++;
- *p++ = *s++;
- if ( *s != '/' )
- *p++ = '\\';
- limit -= 2;
- }
-
- for(; *s && limit; s++, p++, limit--)
- *p = (*s == '/' ? '\\' : *s);
- if ( p[-1] == '\\' && p > path )
- p--;
- *p = EOS;
-
- return path;
- }
- #endif /* O_HPFS */
-
- #if unix
- char *
- PrologPath(const char *p, char *buf)
- { strcpy(buf, p);
-
- return buf;
- }
-
- char *
- OsPath(const char *p, char *buf)
- { strcpy(buf, p);
-
- return buf;
- }
- #endif /*unix*/
-
- #if O_XOS
- char *
- PrologPath(const char *p, char *buf)
- { _xos_canonical_filename(p, buf);
- if ( !trueFeature(FILE_CASE_FEATURE) )
- strlwr(buf);
-
- return buf;
- }
-
- char *
- OsPath(const char *p, char *buf)
- { strcpy(buf, p);
-
- return buf;
- }
- #endif /* O_XOS */
-
- long
- LastModifiedFile(char *f)
- { char tmp[MAXPATHLEN];
-
- #if defined(HAVE_STAT) || defined(__unix__)
- struct stat buf;
-
- if ( statfunc(OsPath(f, tmp), &buf) < 0 )
- return -1;
-
- return (long)buf.st_mtime;
- #endif
-
- #if tos
- #define DAY (24*60*60L)
- static int msize[] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
- long t;
- int n;
- struct ffblk buf;
- struct dz
- { unsigned int hour : 5; /* hour (0-23) */
- unsigned int min : 6; /* minute (0-59) */
- unsigned int sec : 5; /* seconds in steps of 2 */
- unsigned int year : 7; /* year (0=1980) */
- unsigned int mon : 4; /* month (1-12) */
- unsigned int day : 5; /* day (1-31) */
- } *dz;
-
- if ( findfirst(OsPath(f, tmp), &buf, FA_HIDDEN) != 0 )
- return -1;
- dz = (struct dz *) &buf.ff_ftime;
- DEBUG(2, Sdprintf("%d/%d/%d %d:%d:%d\n",
- dz->day, dz->mon, dz->year+1980, dz->hour, dz->min, dz->sec));
-
- t = (10*365+2) * DAY; /* Start of 1980 */
- for(n=0; n < dz->year; n++)
- t += ((n % 4) == 0 ? 366 : 365) * DAY;
- for(n=1; n < dz->mon; n++)
- t += msize[n+1] * DAY;
- t += (dz->sec * 2) + (dz->min * 60) + (dz->hour *60*60L);
-
- return t;
- #endif
- }
-
-
- #ifndef F_OK
- #define F_OK 0
- #endif
-
- bool
- ExistsFile(const char *path)
- { char tmp[MAXPATHLEN];
-
- #ifdef HAVE_ACCESS
- if ( access(OsPath(path, tmp), F_OK) == 0 )
- succeed;
- fail;
- #else
- #if defined(HAVE_STAT) || defined(__unix__)
- struct stat buf;
-
- if ( statfunc(OsPath(path, tmp), &buf) == -1 ||
- (buf.st_mode & S_IFMT) != S_IFREG )
- fail;
- succeed;
- #endif
-
- #if tos
- struct ffblk buf;
-
- if ( findfirst(OsPath(path, tmp), &buf, FA_HIDDEN) == 0 )
- { DEBUG(2, Sdprintf("%s (%s) exists\n", path, OsPath(path)));
- succeed;
- }
- DEBUG(2, Sdprintf("%s (%s) does not exist\n", path, OsPath(path)));
- fail;
- #endif
- #endif
- }
-
- bool
- AccessFile(const char *path, int mode)
- { char tmp[MAXPATHLEN];
- #ifdef HAVE_ACCESS
- int m = 0;
-
- if ( mode == ACCESS_EXIST )
- m = F_OK;
- else
- { if ( mode & ACCESS_READ ) m |= R_OK;
- if ( mode & ACCESS_WRITE ) m |= W_OK;
- #ifdef X_OK
- if ( mode & ACCESS_EXECUTE ) m |= X_OK;
- #endif
- }
-
- return access(OsPath(path, tmp), m) == 0 ? TRUE : FALSE;
- #endif
-
- #ifdef tos
- struct ffblk buf;
-
- if ( findfirst(OsPath(path, tmp), &buf, FA_DIREC|FA_HIDDEN) != 0 )
- fail; /* does not exists */
- if ( (mode & ACCESS_WRITE) && (buf.ff_attrib & FA_RDONLY) )
- fail; /* readonly file */
-
- succeed;
- #endif
- }
-
- bool
- ExistsDirectory(const char *path)
- { char tmp[MAXPATHLEN];
- char *ospath = OsPath(path, tmp);
-
- #if defined(HAVE_STAT) || defined(__unix__)
- struct stat buf;
-
- if ( statfunc(ospath, &buf) < 0 )
- fail;
-
- if ( (buf.st_mode & S_IFMT) == S_IFDIR )
- succeed;
-
- fail;
- #endif
-
- #ifdef tos
- struct ffblk buf;
-
- if ( findfirst(ospath, &buf, FA_DIREC|FA_HIDDEN) == 0 &&
- buf.ff_attrib & FA_DIREC )
- succeed;
- if ( streq(ospath, ".") || streq(ospath, "..") ) /* hack */
- succeed;
- fail;
- #endif
- }
-
-
- long
- SizeFile(const char *path)
- { char tmp[MAXPATHLEN];
- struct stat buf;
-
- #if defined(HAVE_STAT) || defined(__unix__)
- if ( statfunc(OsPath(path, tmp), &buf) == -1 )
- return -1;
- #endif
-
- return buf.st_size;
- }
-
-
- int
- RemoveFile(const char *path)
- { char tmp[MAXPATHLEN];
-
- #ifdef HAVE_REMOVE
- return remove(OsPath(path, tmp)) == 0 ? TRUE : FALSE;
- #else
- return unlink(OsPath(path, tmp)) == 0 ? TRUE : FALSE;
- #endif
- }
-
-
- bool
- RenameFile(const char *old, const char *new)
- { char oldbuf[MAXPATHLEN];
- char newbuf[MAXPATHLEN];
- char *osold, *osnew;
-
- osold = OsPath(old, oldbuf);
- osnew = OsPath(new, newbuf);
-
- #ifdef HAVE_RENAME
- return rename(osold, osnew) == 0 ? TRUE : FALSE;
- #else
- { int rval;
-
- unlink(osnew);
- if ( (rval = link(osold, osnew)) == 0
- && (rval = unlink(osold)) != 0)
- unlink(osnew);
-
- if ( rval == 0 )
- succeed;
-
- fail;
- }
- #endif /*HAVE_RENAME*/
- }
-
- bool
- SameFile(const char *f1, const char *f2)
- { if ( trueFeature(FILE_CASE_FEATURE) )
- { if ( streq(f1, f2) )
- succeed;
- } else
- { if ( stricmp(f1, f2) == 0 )
- succeed;
- }
-
- #ifdef unix /* doesn't work on most not Unix's */
- { struct stat buf1;
- struct stat buf2;
- char tmp[MAXPATHLEN];
-
- if ( statfunc(OsPath(f1, tmp), &buf1) != 0 ||
- statfunc(OsPath(f2, tmp), &buf2) != 0 )
- fail;
- if ( buf1.st_ino == buf2.st_ino && buf1.st_dev == buf2.st_dev )
- succeed;
- }
- #endif
- #ifdef O_XOS
- { char p1[MAXPATHLEN];
- char p2[MAXPATHLEN];
-
- _xos_limited_os_filename(f1, p1);
- _xos_limited_os_filename(f2, p2);
- if ( trueFeature(FILE_CASE_FEATURE) )
- { if ( streq(p1, p2) )
- succeed;
- } else
- { if ( stricmp(p1, p2) == 0 )
- succeed;
- }
- }
- #endif /*O_XOS*/
- /* Amazing! There is no simple way to check two files for identity. */
- /* stat() and fstat() both return dummy values for inode and device. */
- /* this is fine as OS'es not supporting symbolic links don't need this */
-
- fail;
- }
-
-
- bool
- MarkExecutable(const char *name)
- {
- #if (defined(HAVE_STAT) && defined(HAVE_CHMOD)) || defined(__unix__)
- struct stat buf;
- int um;
-
- um = umask(0777);
- umask(um);
- if ( statfunc(name, &buf) == -1 )
- { term_t file = PL_new_term_ref();
-
- PL_put_atom_chars(file, name);
- PL_error(NULL, 0, OsError(), ERR_FILE_OPERATION,
- ATOM_stat, ATOM_file, file);
- }
-
- if ( (buf.st_mode & 0111) == (~um & 0111) )
- succeed;
-
- buf.st_mode |= 0111 & ~um;
- if ( chmod(name, buf.st_mode) == -1 )
- { term_t file = PL_new_term_ref();
-
- PL_put_atom_chars(file, name);
- PL_error(NULL, 0, OsError(), ERR_FILE_OPERATION,
- ATOM_chmod, ATOM_file, file);
- }
- #endif /* defined(HAVE_STAT) && defined(HAVE_CHMOD) */
-
- succeed;
- }
-
- /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- char *AbsoluteFile(const char *file, char *path)
-
- Expand a file specification to a system-wide unique description of
- the file that can be passed to the file functions that take a path
- as argument. Path should refer to the same file, regardless of the
- current working directory. On Unix absolute file names are used
- for this purpose.
-
- This function is based on a similar (primitive) function in
- Edinburgh C-Prolog.
-
- char *BaseName(path)
- char *path;
-
- Return the basic file name for a file having path `path'.
-
- char *DirName(const char *path, char *dir)
-
- Return the directory name for a file having path `path'.
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
-
- #if defined(HAVE_SYMLINKS) && (defined(HAVE_STAT) || defined(__unix__))
- #define O_CANONISE_DIRS
-
- struct canonical_dir
- { char * name; /* name of directory */
- char * canonical; /* canonical name of directory */
- dev_t device; /* device number */
- ino_t inode; /* inode number */
- CanonicalDir next; /* next in chain */
- };
-
- #define canonical_dirlist (GD->os._canonical_dirlist)
-
- forwards char *canoniseDir(char *);
- #endif /*O_CANONISE_DIRS*/
-
- #define CWDdir (LD->os._CWDdir) /* current directory */
- #define CWDlen (LD->os._CWDlen) /* strlen(CWDdir) */
-
- static void
- initExpand(void)
- {
- #ifdef O_CANONISE_DIRS
- char *dir;
- char *cpaths;
- #endif
-
- CWDdir = NULL;
- CWDlen = 0;
-
- #ifdef O_CANONISE_DIRS
- { char envbuf[MAXPATHLEN];
-
- if ( (cpaths = getenv3("CANONICAL_PATHS", envbuf, sizeof(envbuf))) )
- { char buf[MAXPATHLEN];
-
- while(*cpaths)
- { char *e;
-
- if ( (e = strchr(cpaths, ':')) )
- { int l = e-cpaths;
-
- strncpy(buf, cpaths, l);
- buf[l] = EOS;
- cpaths += l+1;
- canoniseDir(buf);
- } else
- { canoniseDir(cpaths);
- break;
- }
- }
- }
-
- if ( (dir = getenv3("HOME", envbuf, sizeof(envbuf))) ) canoniseDir(dir);
- if ( (dir = getenv3("PWD", envbuf, sizeof(envbuf))) ) canoniseDir(dir);
- if ( (dir = getenv3("CWD", envbuf, sizeof(envbuf))) ) canoniseDir(dir);
- }
- #endif
- }
-
- #ifdef O_CANONISE_DIRS
-
- static char *
- canoniseDir(char *path)
- { CanonicalDir d;
- struct stat buf;
- char tmp[MAXPATHLEN];
-
- DEBUG(1, Sdprintf("canoniseDir(%s) --> ", path));
-
- for(d = canonical_dirlist; d; d = d->next)
- { if ( streq(d->name, path) )
- { if ( d->name != d->canonical )
- strcpy(path, d->canonical);
-
- DEBUG(1, Sdprintf("(lookup) %s\n", path));
- return path;
- }
- }
-
- if ( statfunc(OsPath(path, tmp), &buf) == 0 )
- { CanonicalDir dn = allocHeap(sizeof(struct canonical_dir));
- char dirname[MAXPATHLEN];
- char *e = path + strlen(path);
-
- dn->next = canonical_dirlist;
- dn->name = store_string(path);
- dn->inode = buf.st_ino;
- dn->device = buf.st_dev;
-
- do
- { strncpy(dirname, path, e-path);
- dirname[e-path] = EOS;
- if ( statfunc(OsPath(dirname, tmp), &buf) < 0 )
- break;
-
- DEBUG(2, Sdprintf("Checking %s (dev=%d,ino=%d)\n",
- dirname, buf.st_dev, buf.st_ino));
-
- for(d = canonical_dirlist; d; d = d->next)
- { if ( d->inode == buf.st_ino && d->device == buf.st_dev )
- { canonical_dirlist = dn;
-
- DEBUG(2, Sdprintf("Hit with %s (dev=%d,ino=%d)\n",
- d->canonical, d->device, d->inode));
-
- strcpy(dirname, d->canonical);
- strcat(dirname, e);
- strcpy(path, dirname);
- dn->canonical = store_string(path);
- DEBUG(1, Sdprintf("(replace) %s\n", path));
- return path;
- }
- }
-
- for(e--; *e != '/' && e > path + 1; e-- )
- ;
-
- } while( e > path );
-
- dn->canonical = dn->name;
- canonical_dirlist = dn;
-
- DEBUG(1, Sdprintf("(new, existing) %s\n", path));
- return path;
- }
-
- DEBUG(1, Sdprintf("(nonexisting) %s\n", path));
- return path;
- }
-
- #else
-
- #define canoniseDir(d)
-
- #endif /*O_CANONISE_DIRS*/
-
-
- static char *
- canoniseFileName(char *path)
- { char *out = path, *in = path;
- char *osave[100];
- int osavep = 0;
-
- while( in[0] == '/' && in[1] == '.' && in[2] == '.' && in[3] == '/' )
- in += 3;
- if ( in[0] == '/' )
- *out++ = '/';
- osave[osavep++] = out;
-
- while(*in)
- { if (*in == '/')
- {
- again:
- if ( *in )
- { while( in[1] == '/' )
- in++;
- if ( in[1] == '.' && (in[2] == '/' || in[2] == EOS) )
- { in += 2;
- goto again;
- }
- if ( in[1] == '.' && in[2] == '.' &&
- (in[3] == '/' || in[3] == EOS) && osavep > 0 )
- { out = osave[--osavep];
- in += 3;
- goto again;
- }
- }
- if ( *in )
- in++;
- if ( out > path && out[-1] != '/' )
- *out++ = '/';
- osave[osavep++] = out;
- } else
- *out++ = *in++;
- }
- *out++ = *in++;
-
- return path;
- }
-
-
- char *
- canonisePath(char *path)
- { if ( !trueFeature(FILE_CASE_FEATURE) )
- strlwr(path);
-
- canoniseFileName(path);
-
- #ifdef O_CANONISE_DIRS
- { char *e;
- char dirname[MAXPATHLEN];
-
- e = path + strlen(path) - 1;
- for( ; *e != '/' && e > path; e-- )
- ;
- strncpy(dirname, path, e-path);
- dirname[e-path] = EOS;
- canoniseDir(dirname);
- strcat(dirname, e);
- strcpy(path, dirname);
- }
- #endif
-
- return path;
- }
-
-
- static char *
- takeWord(const char **string, char *wrd)
- { const char *s = *string;
- char *q = wrd;
- int left = MAXPATHLEN-1;
-
- while( isAlpha(*s) || *s == '_' )
- { if ( --left < 0 )
- { PL_error(NULL, 0, NULL, ERR_REPRESENTATION,
- ATOM_max_variable_length);
- return NULL;
- }
- *q++ = *s++;
- }
- *q = EOS;
-
- *string = s;
- return wrd;
- }
-
-
- bool
- expandVars(const char *pattern, char *expanded)
- { int size = 0;
- char c;
- char word[MAXPATHLEN];
-
- if ( *pattern == '~' )
- { char *user;
- char *value;
- int l;
-
- pattern++;
- user = takeWord(&pattern, word);
- if ( user[0] == EOS ) /* ~/bla */
- {
- #ifdef O_XOS
- value = _xos_home();
- #else /*O_XOS*/
- if ( !(value = GD->os.myhome) )
- { char envbuf[MAXPATHLEN];
-
- if ( (value = getenv3("HOME", envbuf, sizeof(envbuf))) )
- { value = GD->os.myhome = store_string(PrologPath(value, word));
- } else
- { value = GD->os.myhome = "/";
- }
- }
- #endif /*O_XOS*/
- } else /* ~fred */
- #ifdef HAVE_GETPWNAM
- { struct passwd *pwent;
-
- if ( GD->os.fred && !streq(GD->os.fred, user) )
- { value = GD->os.fredshome;
- } else
- { if ( !(pwent = getpwnam(user)) )
- { if ( fileerrors )
- { term_t name = PL_new_term_ref();
-
- PL_put_atom_chars(name, user);
- PL_error(NULL, 0, NULL, ERR_EXISTENCE, ATOM_user, name);
- }
- fail;
- }
- if ( GD->os.fred )
- remove_string(GD->os.fred);
- if ( GD->os.fredshome )
- remove_string(GD->os.fredshome);
-
- GD->os.fred = store_string(user);
- value = GD->os.fredshome = store_string(pwent->pw_dir);
- }
- }
- #else
- { if ( fileerrors )
- PL_error(NULL, 0, NULL, ERR_NOTIMPLEMENTED, PL_new_atom("user_info"));
-
- fail;
- }
- #endif
- size += (l = (int) strlen(value));
- if ( size >= MAXPATHLEN )
- return PL_error(NULL, 0, NULL, ERR_REPRESENTATION, ATOM_max_path_length);
- strcpy(expanded, value);
- expanded += l;
- }
-
- for( ;; )
- { switch( c = *pattern++ )
- { case EOS:
- break;
- case '$':
- { char envbuf[MAXPATHLEN];
- char *var = takeWord(&pattern, word);
- char *value = getenv3(var, envbuf, sizeof(envbuf));
- int l;
-
- if ( value == (char *) NULL )
- { if ( fileerrors )
- { term_t name = PL_new_term_ref();
-
- PL_put_atom_chars(name, var);
- PL_error(NULL, 0, NULL, ERR_EXISTENCE, ATOM_variable, name);
- }
-
- fail;
- }
- size += (l = (int)strlen(value));
- if ( size >= MAXPATHLEN )
- return PL_error(NULL, 0, NULL, ERR_REPRESENTATION,
- ATOM_max_path_length);
- strcpy(expanded, value);
- expanded += l;
-
- continue;
- }
- default:
- if ( ++size >= MAXPATHLEN )
- return PL_error(NULL, 0, NULL, ERR_REPRESENTATION,
- ATOM_max_path_length);
- *expanded++ = c;
-
- continue;
- }
- break;
- }
-
- if ( ++size >= MAXPATHLEN )
- return PL_error(NULL, 0, NULL, ERR_REPRESENTATION,
- ATOM_max_path_length);
- *expanded = EOS;
-
- succeed;
- }
-
-
- static int
- ExpandFile(const char *pattern, char **vector)
- { char expanded[MAXPATHLEN];
- int matches = 0;
-
- if ( !expandVars(pattern, expanded) )
- return -1;
-
- vector[matches++] = store_string(expanded);
-
- return matches;
- }
-
-
- char *
- ExpandOneFile(const char *spec, char *file)
- { char *vector[256];
- int size;
-
- switch( (size=ExpandFile(spec, vector)) )
- { case -1:
- return NULL;
- case 0:
- { term_t tmp = PL_new_term_ref();
-
- PL_put_atom_chars(tmp, spec);
- PL_error(NULL, 0, "no match", ERR_EXISTENCE, ATOM_file, tmp);
-
- return NULL;
- }
- case 1:
- strcpy(file, vector[0]);
- remove_string(vector[0]);
- return file;
- default:
- { term_t tmp = PL_new_term_ref();
- int n;
-
- for(n=0; n<size; n++)
- remove_string(vector[n]);
- PL_put_atom_chars(tmp, spec);
- PL_error(NULL, 0, "ambiguous", ERR_EXISTENCE, ATOM_file, tmp);
-
- return NULL;
- }
- }
- }
-
-
- #ifdef O_HASDRIVES
-
- int
- IsAbsolutePath(const char *p) /* /d:/ or d:/ */
- { if ( p[0] == '/' && p[2] == ':' && isLetter(p[1]) &&
- (p[3] == '/' || p[3] == '\0') )
- succeed;
-
- if ( p[1] == ':' && isLetter(p[0]) && (p[2] == '/' || p[2] == '\0') )
- succeed;
-
- fail;
- }
-
-
- static inline int
- isDriveRelativePath(const char *p) /* '/...' */
- { return p[0] == '/' && !IsAbsolutePath(p);
- }
-
- #ifdef __WIN32__
- #undef mkdir
- #include <direct.h>
- #define mkdir _xos_mkdir
- #endif
-
- static int
- GetCurrentDriveLetter()
- {
- #ifdef OS2
- return _getdrive();
- #endif
- #ifdef __WIN32__
- return _getdrive() + 'a' - 1;
- #endif
- #ifdef __WATCOMC__
- { unsigned drive;
- _dos_getdrive(&drive);
- return = 'a' + drive - 1;
- }
- #endif
- }
-
- #else /*O_HASDRIVES*/
-
- int
- IsAbsolutePath(const char *p)
- { return p[0] == '/';
- }
-
- #endif /*O_HASDRIVES*/
-
- #define isRelativePath(p) ( p[0] == '.' )
-
-
- char *
- AbsoluteFile(const char *spec, char *path)
- { char tmp[MAXPATHLEN];
- char buf[MAXPATHLEN];
- char *file;
-
- PrologPath(spec, buf);
- if ( !(file = ExpandOneFile(buf, tmp)) )
- return (char *) NULL;
-
- if ( IsAbsolutePath(file) )
- { strcpy(path, file);
-
- return canonisePath(path);
- }
-
- #ifdef O_HASDRIVES
- if ( isDriveRelativePath(file) ) /* /something --> d:/something */
- { if ((strlen(file) + 3) > MAXPATHLEN)
- { PL_error(NULL, 0, NULL, ERR_REPRESENTATION, ATOM_max_path_length);
- return (char *) NULL;
- }
- path[0] = GetCurrentDriveLetter();
- path[1] = ':';
- strcpy(&path[2], file);
- return canonisePath(path);
- }
- #endif /*O_HASDRIVES*/
-
- if ( CWDlen == 0 )
- { char buf[MAXPATHLEN];
- char *rval;
-
- /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- On SunOs, getcwd() is using popen() to read the output of /bin/pwd. This
- is slow and appears not to cooperate with profile/3. getwd() is supposed
- to be implemented directly. What about other Unixes?
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
-
- #if defined(HAVE_GETWD) && (defined(__sun__) || !defined(HAVE_GETCWD))
- rval = getwd(buf);
- #else
- rval = getcwd(buf, MAXPATHLEN);
- #endif
- if ( !rval )
- { term_t tmp = PL_new_term_ref();
-
- PL_put_atom(tmp, ATOM_dot);
- PL_error(NULL, 0, OsError(), ERR_FILE_OPERATION,
- ATOM_getcwd, ATOM_directory, tmp);
- }
-
- canonisePath(buf);
- CWDlen = strlen(buf);
- buf[CWDlen++] = '/';
- buf[CWDlen] = EOS;
-
- if ( CWDdir )
- remove_string(CWDdir);
- CWDdir = store_string(buf);
- }
-
- if ( (CWDlen + strlen(file) + 1) >= MAXPATHLEN )
- { PL_error(NULL, 0, NULL, ERR_REPRESENTATION, ATOM_max_path_length);
- return (char *) NULL;
- }
-
- strcpy(path, CWDdir);
- if ( file[0] != EOS )
- strcpy(&path[CWDlen], file);
- if ( strchr(file, '.') || strchr(file, '/') )
- return canonisePath(path);
- else
- return path;
- }
-
-
- char *
- BaseName(register char *f)
- { register char *base;
-
- for(base = f; *f; f++)
- { if (*f == '/')
- base = f+1;
- }
-
- return base;
- }
-
-
- char *
- DirName(const char *f, char *dir)
- { const char *base, *p;
-
- for(base = p = f; *p; p++)
- { if (*p == '/' && p[1] != EOS )
- base = p+1;
- }
- strncpy(dir, f, base-f);
- dir[base-f] = EOS;
-
- return dir;
- }
-
-
- char *
- ReadLink(const char *f, char *buf)
- {
- #ifdef HAVE_READLINK
- int n;
-
- if ( (n=readlink(f, buf, MAXPATHLEN-1)) > 0 )
- { buf[n] = EOS;
- return buf;
- }
- #endif
-
- return NULL;
- }
-
-
- static char *
- DeRefLink1(const char *f, char *lbuf)
- { char buf[MAXPATHLEN];
- char *l;
-
- if ( (l=ReadLink(f, buf)) )
- { if ( l[0] == '/' ) /* absolute path */
- { strcpy(lbuf, buf);
- return lbuf;
- } else
- { char *q;
-
- strcpy(lbuf, f);
- q = &lbuf[strlen(lbuf)];
- while(q>lbuf && q[-1] != '/')
- q--;
- strcpy(q, l);
-
- canoniseFileName(lbuf);
-
- return lbuf;
- }
- }
-
- return NULL;
- }
-
-
- char *
- DeRefLink(const char *link, char *buf)
- { char tmp[MAXPATHLEN];
- char *f;
- int n = 20; /* avoid loop! */
-
- while((f=DeRefLink1(link, tmp)) && n-- > 0)
- link = f;
-
- if ( n > 0 )
- { strcpy(buf, link);
- return buf;
- } else
- return NULL;
- }
-
-
-
- /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- bool ChDir(path)
- char *path;
-
- Change the current working directory to `path'. File names may depend
- on `path'.
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
-
- bool
- ChDir(const char *path)
- { char ospath[MAXPATHLEN];
- char tmp[MAXPATHLEN];
-
- OsPath(path, ospath);
-
- if ( path[0] == EOS || streq(path, ".") ||
- (CWDdir && streq(path, CWDdir)) )
- succeed;
-
- AbsoluteFile(path, tmp);
-
- if ( chdir(ospath) == 0 )
- { int len;
-
- len = strlen(tmp);
- if ( len == 0 || tmp[len-1] != '/' )
- { tmp[len++] = '/';
- tmp[len] = EOS;
- }
- CWDlen = len;
- if ( CWDdir )
- remove_string(CWDdir);
- CWDdir = store_string(tmp);
-
- succeed;
- }
-
- fail;
- }
-
-
-
- /********************************
- * TIME CONVERSION *
- *********************************/
-
- /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- struct tm *LocalTime(time)
- long *time;
-
- Convert time in Unix internal form (seconds since Jan 1 1970) into a
- structure providing easier access to the time.
-
- For non-Unix systems: struct time is supposed to look like this.
- Move This definition to pl-os.h and write the conversion functions
- here.
-
- struct tm {
- int tm_sec; / * second in the minute (0-59)* /
- int tm_min; / * minute in the hour (0-59) * /
- int tm_hour; / * hour of the day (0-23) * /
- int tm_mday; / * day of the month (1-31) * /
- int tm_mon; / * month of the year (1-12) * /
- int tm_year; / * year (0 = 1900) * /
- int tm_wday; / * day in the week (1-7, 1 = sunday) * /
- int tm_yday; / * day in the year (0-365) * /
- int tm_isdst; / * daylight saving time info * /
- };
-
- long Time()
-
- Return time in seconds after Jan 1 1970 (Unix' time notion).
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
-
- struct tm *
- LocalTime(long int *t)
- { return localtime((const time_t *) t);
- }
-
-
- static long
- Time(void)
- { return (long)time((time_t *) NULL);
- }
-
-
- /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- TERMINAL IO MANIPULATION
-
- ResetStdin()
- Clear the Sinput buffer after a saved state. Only necessary
- if O_SAVE is defined.
-
- PushTty()
- Push the tty to the specified state.
-
- PopTty()
- Restore the tty state.
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
-
- static void
- ResetStdin()
- { Sinput->limitp = Sinput->bufp = Sinput->buffer;
- if ( !GD->os.org_terminal.read )
- GD->os.org_terminal = *Sinput->functions;
- }
-
- static int
- Swrite_protocol(void *handle, char *buf, int size)
- { int rval;
- #ifdef HAVE_CLOCK
- long oldclock = clock();
- #endif
-
- protocol(buf, size);
-
- rval = (*GD->os.org_terminal.write)(handle, buf, size);
-
- #ifdef HAVE_CLOCK
- clock_wait_ticks += clock() - oldclock;
- #endif
-
- return rval;
- }
-
- int
- Sread_terminal(void *handle, char *buf, int size)
- { long h = (long)handle;
- atom_t sfn = source_file_name; /* save over call-back */
- int sln = source_line_no;
- int fd = (int)h;
-
- if ( GD->os.prompt_next && ttymode != TTY_RAW )
- { Putf("%s", PrologPrompt());
-
- GD->os.prompt_next = FALSE;
- }
-
- pl_ttyflush();
- PL_dispatch(fd, PL_DISPATCH_WAIT);
- size = (*GD->os.org_terminal.read)(handle, buf, size);
-
- if ( size == 0 ) /* end-of-file */
- { if ( fd == 0 )
- { Sclearerr(Sinput);
- GD->os.prompt_next = TRUE;
- }
- } else if ( size > 0 && buf[size-1] == '\n' )
- GD->os.prompt_next = TRUE;
-
- source_line_no = sln;
- source_file_name = sfn;
-
- return size;
- }
-
- void
- ResetTty()
- { startCritical;
- ResetStdin();
-
- if ( !GD->os.iofunctions.read )
- { GD->os.iofunctions = *Sinput->functions;
- GD->os.iofunctions.read = Sread_terminal;
- GD->os.iofunctions.write = Swrite_protocol;
-
- Sinput->functions =
- Soutput->functions =
- Serror->functions = &GD->os.iofunctions;
- }
- GD->os.prompt_next = TRUE;
- endCritical;
- }
-
- #ifdef O_HAVE_TERMIO /* sys/termios.h or sys/termio.h */
-
- #ifndef HAVE_TCSETATTR
- #ifndef NO_SYS_IOCTL_H_WITH_SYS_TERMIOS_H
- #include <sys/ioctl.h>
- #endif
- #ifndef TIOCGETA
- #define TIOCGETA TCGETA
- #endif
- #endif
-
- bool
- PushTty(ttybuf *buf, int mode)
- { struct termios tio;
-
- buf->mode = ttymode;
- ttymode = mode;
-
- if ( GD->cmdline.notty )
- succeed;
-
- #ifdef HAVE_TCSETATTR
- if ( tcgetattr(0, &buf->tab) ) /* save the old one */
- fail;
- #else
- if ( ioctl(0, TIOCGETA, &buf->tab) ) /* save the old one */
- fail;
- #endif
-
- tio = buf->tab;
-
- switch( mode )
- { case TTY_RAW:
- #if defined(HAVE_TCSETATTR) && defined(HAVE_CFMAKERAW)
- cfmakeraw(&tio);
- tio.c_oflag = buf->tab.c_oflag; /* donot change output modes */
- tio.c_lflag |= ISIG;
- #else
- tio.c_lflag &= ~(ECHO|ICANON);
- tio.c_cc[VTIME] = 0, tio.c_cc[VMIN] = 1;
- #endif
- break;
- case TTY_OUTPUT:
- tio.c_oflag |= (OPOST|ONLCR);
- break;
- case TTY_SAVE:
- succeed;
- default:
- sysError("Unknown PushTty() mode: %d", mode);
- /*NOTREACHED*/
- }
-
- #ifdef HAVE_TCSETATTR
- if ( tcsetattr(0, TCSANOW, &tio) != 0 )
- { static int MTOK_warned; /* MT-OK */
-
- if ( !MTOK_warned++ )
- warning("Failed to set terminal: %s", OsError());
- }
- #else
- #ifdef TIOCSETAW
- ioctl(0, TIOCSETAW, &tio);
- #else
- ioctl(0, TCSETAW, &tio);
- ioctl(0, TCXONC, (void *)1);
- #endif
- #endif
-
- succeed;
- }
-
-
- bool
- PopTty(ttybuf *buf)
- { ttymode = buf->mode;
-
- if ( GD->cmdline.notty )
- succeed;
-
- #ifdef HAVE_TCSETATTR
- tcsetattr(0, TCSANOW, &buf->tab);
- #else
- #ifdef TIOCSETA
- ioctl(0, TIOCSETA, &buf->tab);
- #else
- ioctl(0, TCSETA, &buf->tab);
- ioctl(0, TCXONC, (void *)1);
- #endif
- #endif
-
- succeed;
- }
-
- #else /* O_HAVE_TERMIO */
-
- #ifdef HAVE_SGTTYB
-
- bool
- PushTty(ttybuf *buf, int mode)
- { struct sgttyb tio;
-
- buf->mode = ttymode;
- ttymode = mode;
-
- if ( GD->cmdline.notty )
- succeed;
-
- if ( ioctl(0, TIOCGETP, &buf->tab) ) /* save the old one */
- fail;
- tio = buf->tab;
-
- switch( mode )
- { case TTY_RAW:
- tio.sg_flags |= CBREAK;
- tio.sg_flags &= ~ECHO;
- break;
- case TTY_OUTPUT:
- tio.sg_flags |= (CRMOD);
- break;
- case TTY_SAVE:
- succeed;
- default:
- sysError("Unknown PushTty() mode: %d", mode);
- /*NOTREACHED*/
- }
-
-
- ioctl(0, TIOCSETP, &tio);
- ioctl(0, TIOCSTART, NULL);
-
- succeed;
- }
-
-
- bool
- PopTty(ttybuf *buf)
- { ttymode = buf->mode;
-
- if ( GD->cmdline.notty )
- succeed;
-
- ioctl(0, TIOCSETP, &buf->tab);
- ioctl(0, TIOCSTART, NULL);
-
- succeed;
- }
-
- #else /*HAVE_SGTTYB*/
-
- bool
- PushTty(buf, mode)
- ttybuf *buf;
- int mode;
- { buf->mode = ttymode;
- ttymode = mode;
-
- succeed;
- }
-
-
- bool
- PopTty(buf)
- ttybuf *buf;
- { ttymode = buf->mode;
- if ( ttymode != TTY_RAW )
- GD->os.prompt_next = TRUE;
-
- succeed;
- }
-
- #endif /*HAVE_SGTTYB*/
- #endif /*O_HAVE_TERMIO*/
-
-
- /********************************
- * ENVIRONMENT CONTROL *
- *********************************/
-
- /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- Simple library to manipulate the Unix environment. The modified
- environment will be passed to child processes and the can also be
- requested via getenv/2 from Prolog. Functions
-
- char *Setenv(name, value)
- char *name, *value;
-
- Set the Unix environment variable with name `name'. If it exists
- its value is changed, otherwise a new entry in the environment is
- created. The return value is a pointer to the old value, or NULL if
- the variable is new.
-
- char *Unsetenv(name)
- char *name;
-
- Delete a variable from the environment. Return value is the old
- value, or NULL if the variable did not exist.
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
-
- #ifndef __WIN32__
- char *
- getenv3(const char *name, char *buf, int len)
- { char *s = getenv(name);
-
- if ( s && strlen(s) < len )
- { strcpy(buf, s);
-
- return buf;
- }
-
- return NULL;
- }
-
- int
- getenvl(const char *name)
- { char *s;
-
- if ( (s = getenv(name)) )
- return strlen(s);
-
- return -1;
- }
- #endif
-
- #if HAVE_PUTENV
-
- int
- Setenv(char *name, char *value)
- { char *buf = alloca(strlen(name) + strlen(value) + 2);
-
- if ( buf )
- { Ssprintf(buf, "%s=%s", name, value);
-
- if ( putenv(store_string(buf)) < 0 )
- return PL_error("setenv", 2, NULL, ERR_NOMEM);
- } else
- return PL_error("setenv", 2, NULL, ERR_NOMEM);
-
- succeed;
- }
-
- int
- Unsetenv(char *name)
- { return Setenv(name, "");
- }
-
- static void
- initEnviron()
- {
- }
-
- #else /*HAVE_PUTENV*/
-
- #ifdef tos
- char **environ;
- #else
- extern char **environ; /* Unix predefined environment */
- #endif
-
- /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- Grow the environment array by one and return the (possibly moved) base
- pointer to the new environment.
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
-
- forwards char **growEnviron(char**, int);
- forwards char *matchName(char *, char *);
- forwards void setEntry(char **, char *, char *);
-
- static char **
- growEnviron(char **e, int amount)
- { static int filled;
- static int size = -1;
-
- if ( amount == 0 ) /* reset after a dump */
- { size = -1;
- return e;
- }
-
- if ( size < 0 )
- { register char **env, **e1, **e2;
-
- for(e1=e, filled=0; *e1; e1++, filled++)
- ;
- size = ROUND(filled+10+amount, 32);
- env = (char **)malloc(size * sizeof(char *));
- for ( e1=e, e2=env; *e1; *e2++ = *e1++ )
- ;
- *e2 = (char *) NULL;
- filled += amount;
-
- return env;
- }
-
- filled += amount;
- if ( filled + 1 > size )
- { register char **env, **e1, **e2;
-
- size += 32;
- env = (char **)realloc(e, size * sizeof(char *));
- for ( e1=e, e2=env; *e1; *e2++ = *e1++ )
- ;
- *e2 = (char *) NULL;
-
- return env;
- }
-
- return e;
- }
-
-
- static void
- initEnviron(void)
- { growEnviron(environ, 0);
- }
-
-
- static char *
- matchName(register char *e, register char *name)
- { while( *name && *e == *name )
- e++, name++;
-
- if ( (*e == '=' || *e == EOS) && *name == EOS )
- return (*e == '=' ? e+1 : e);
-
- return (char *) NULL;
- }
-
-
- static void
- setEntry(char **e, char *name, char *value)
- { int l = (int)strlen(name);
-
- *e = (char *) malloc(l + strlen(value) + 2);
- strcpy(*e, name);
- e[0][l++] = '=';
- strcpy(&e[0][l], value);
- }
-
-
- char *
- Setenv(char *name, char *value)
- { char **e;
- char *v;
- int n;
-
- for(n=0, e=environ; *e; e++, n++)
- { if ( (v=matchName(*e, name)) != NULL )
- { if ( !streq(v, value) )
- setEntry(e, name, value);
- return v;
- }
- }
- environ = growEnviron(environ, 1);
- setEntry(&environ[n], name, value);
- environ[n+1] = (char *) NULL;
-
- return (char *) NULL;
- }
-
-
- char *
- Unsetenv(char *name)
- { char **e;
- char *v;
- int n;
-
- for(n=0, e=environ; *e; e++, n++)
- { if ( (v=matchName(*e, name)) != NULL )
- { environ = growEnviron(environ, -1);
- e = &environ[n];
- do
- { e[0] = e[1];
- e++;
- } while(*e);
-
- return v;
- }
- }
-
- return (char *) NULL;
- }
-
- #endif /*HAVE_PUTENV*/
-
- /********************************
- * SYSTEM PROCESSES *
- *********************************/
-
- /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- int System(command)
- char *command;
-
- Invoke a command on the operating system. The return value is the
- exit status of the command. Return value 0 implies succesful
- completion. If you are not running Unix your C-library might provide
- an alternative.
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
-
- #ifdef unix
- #define SPECIFIC_SYSTEM 1
- #if defined(HAVE_SYS_RESOURCE_H)
- #include <sys/resource.h>
- #endif
- #if defined(HAVE_SYS_WAIT_H) || defined(UNION_WAIT)
- #include <sys/wait.h>
- #endif
-
- #ifdef UNION_WAIT
-
- #define wait_t union wait
-
- #ifndef WEXITSTATUS
- #define WEXITSTATUS(s) ((s).w_status)
- #endif
- #ifndef WTERMSIG
- #define WTERMSIG(s) ((s).w_status)
- #endif
-
- #else /*UNION_WAIT*/
-
- #define wait_t int
-
- #ifndef WEXITSTATUS
- # define WEXITSTATUS(stat_val) ((unsigned)(stat_val) >> 8)
- #endif
- #ifndef WIFEXITED
- # define WIFEXITED(stat_val) (((stat_val) & 255) == 0)
- #endif
-
- #endif /*UNION_WAIT*/
-
- int
- System(char *cmd)
- { int pid;
- char *shell = "/bin/sh";
- int rval;
- void (*old_int)();
- void (*old_stop)();
-
- Setenv("PROLOGCHILD", "yes");
-
- if ( (pid = vfork()) == -1 )
- { return PL_error("shell", 2, OsError(), ERR_SYSCALL, ATOM_fork);
- } else if ( pid == 0 ) /* The child */
- { int i;
- int fdmax = getdtablesize();
-
- for(i = 3; i < fdmax; i++)
- close(i);
- stopItimer();
-
- execl(shell, BaseName(shell), "-c", cmd, (char *)0);
- fatalError("Failed to execute %s: %s", shell, OsError());
- fail;
- /*NOTREACHED*/
- } else
- { wait_t status; /* the parent */
- int n;
-
- old_int = signal(SIGINT, SIG_IGN);
- #ifdef SIGTSTP
- old_stop = signal(SIGTSTP, SIG_DFL);
- #endif /* SIGTSTP */
-
- while((n = Wait(&status)) != -1 && n != pid);
- if (n == -1)
- { term_t tmp = PL_new_term_ref();
-
- PL_put_atom_chars(tmp, cmd);
- PL_error("shell", 2, NULL, ERR_SHELL_FAILED, tmp);
-
- rval = 1;
- } else if (WIFEXITED(status))
- { rval = WEXITSTATUS(status);
- #ifdef WIFSIGNALED
- } else if (WIFSIGNALED(status))
- { term_t tmp = PL_new_term_ref();
- int sig = WTERMSIG(status);
-
- PL_put_atom_chars(tmp, cmd);
- PL_error("shell", 2, NULL, ERR_SHELL_SIGNALLED, tmp, sig);
- rval = 1;
- #endif
- } else
- { rval = 1; /* make gcc happy */
- fatalError("Unknown return code from wait(3)");
- /*NOTREACHED*/
- }
- }
-
- signal(SIGINT, old_int); /* restore signal handlers */
- #ifdef SIGTSTP
- signal(SIGTSTP, old_stop);
- #endif /* SIGTSTP */
-
- return rval;
- }
- #endif /* unix */
-
- #ifdef tos
- #define SPECIFIC_SYSTEM 1
- #include <aes.h>
-
- /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- The routine system_via_shell() has been written by Tom Demeijer. Thanks!
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
-
- #define _SHELL_P ((long *)0x4f6L)
- #define SHELL_OK (do_sys != 0)
-
- int cdecl (*do_sys)(const char *cmd); /* Parameter on stack ! */
-
- static int
- system_via_shell(const char *cmd)
- { long oldssp;
-
- oldssp = Super((void *)0L);
- do_sys = (void (*))*_SHELL_P;
- Super((void *)oldssp);
-
- if(cmd==NULL && SHELL_OK)
- return 0;
-
- if (SHELL_OK)
- return do_sys(cmd);
-
- return -1;
- }
-
- int
- System(command)
- char *command;
- { char tmp[MANIPULATION];
- char path[MAXPATHLEN];
- char *cmd_path;
- COMMAND commandline;
- char *s, *q;
- int status, l;
- char *cmd = command;
-
- if ( (status = system_via_shell(command)) != -1 )
- { Sprintf("\033e"); /* get cursor back */
-
- return status;
- }
-
- /* get the name of the executable and store in path */
- for(s=path; *cmd != EOS && !isBlank(*cmd); *s++ = *cmd++)
- ;
- *s = EOS;
- if ( !(cmd_path = Which(path, tmp)) )
- { warning("%s: command not found", path);
- return 1;
- }
-
- /* copy the command in commandline */
- while( isBlank(*cmd) )
- cmd++;
-
- for(l = 0, s = cmd, q = commandline.command_tail; *s && l <= 126; s++ )
- { if ( *s != '\'' )
- { *q++ = (*s == '/' ? '\\' : *s);
- l++;
- }
- }
- commandline.length = l;
- *q = EOS;
-
- /* execute the command */
- if ( (status = (int) Pexec(0, OsPath(cmd_path), &commandline, NULL)) < 0 )
- { warning("Failed to execute %s: %s", command, OsError());
- return 1;
- }
-
- /* clean up after a graphics application */
- if ( strpostfix(cmd_path, ".prg") || strpostfix(cmd_path, ".tos") )
- { graf_mouse(M_OFF, NULL); /* get rid of the mouse */
- Sprintf("\033e\033E"); /* clear screen and get cursor */
- }
-
- return status;
- }
- #endif
-
- #ifdef HAVE_WINEXEC /* Windows 3.1 */
- #define SPECIFIC_SYSTEM 1
-
- int
- System(char *command)
- { char *msg;
- int rval = WinExec(command, SW_SHOWNORMAL);
-
- if ( rval < 32 )
- { switch( rval )
- { case 0: msg = "Not enough memory"; break;
- case 2: msg = "File not found"; break;
- case 3: msg = "No path"; break;
- case 5: msg = "Unknown error"; break;
- case 6: msg = "Lib requires separate data segment"; break;
- case 8: msg = "Not enough memory"; break;
- case 10: msg = "Incompatible Windows version"; break;
- case 11: msg = "Bad executable file"; break;
- case 12: msg = "Incompatible operating system"; break;
- case 13: msg = "MS-DOS 4.0 executable"; break;
- case 14: msg = "Unknown executable file type"; break;
- case 15: msg = "Real-mode application"; break;
- case 16: msg = "Cannot start multiple copies"; break;
- case 19: msg = "Executable is compressed"; break;
- case 20: msg = "Invalid DLL"; break;
- case 21: msg = "Application is 32-bits"; break;
- default: msg = "Unknown error";
- }
-
- warning("Could not start %s: error %d (%s)",
- command, rval, msg);
- return 1;
- }
-
- return 0;
- }
- #endif
-
-
- #ifdef __WIN32__
- #define SPECIFIC_SYSTEM 1
-
- /* definition in pl-nt.c */
- #endif
-
- /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- Nothing special is needed. Just hope the C-library defines system().
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
-
- #ifndef SPECIFIC_SYSTEM
-
- int
- System(command)
- char *command;
- { return system(command);
- }
-
- #endif
-
- /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- char *Symbols(char *buf)
-
- Return the path name of the executable of SWI-Prolog. Used by the -c
- compiler to generate the #!<path> header line and by the incremental
- loader, who gives this path to ld, using ld -A <path>.
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
-
- #ifndef __WIN32__ /* Win32 version in pl-nt.c */
-
- char *
- Symbols(char *buffer)
- { char *file;
- char buf[MAXPATHLEN];
- char tmp[MAXPATHLEN];
-
- PrologPath(GD->cmdline.argv[0], buf);
- file = Which(buf, tmp);
-
- #if __unix__ /* argv[0] can be an #! script! */
- if ( file )
- { int n, fd;
- char buf[MAXPATHLEN];
-
- if ( (fd = open(file, O_RDONLY)) < 0 )
- { warning("Cannot open %s: %s", file, OsError());
- return file;
- }
-
- if ( (n=read(fd, buf, sizeof(buf)-1)) > 0 )
- { close(fd);
-
- buf[n] = EOS;
- if ( strncmp(buf, "#!", 2) == 0 )
- { char *s = &buf[2], *q;
- while(*s && isBlank(*s))
- s++;
- for(q=s; *q && !isBlank(*q); q++)
- ;
- *q = EOS;
-
- strcpy(buffer, s);
-
- return buffer;
- }
- }
-
- close(fd);
- }
- #endif /*__unix__*/
-
- if ( file )
- strcpy(buffer, file);
- else
- strcpy(buffer, buf);
-
- return buffer;
- }
- #endif /*__WIN32__*/
-
-
- #if unix
- static char *
- okToExec(const char *s)
- { struct stat stbuff;
-
- if (statfunc(s, &stbuff) == 0 && /* stat it */
- (stbuff.st_mode & S_IFMT) == S_IFREG && /* check for file */
- access(s, X_OK) == 0) /* can be executed? */
- return (char *)s;
- else
- return (char *) NULL;
- }
- #define PATHSEP ':'
- #endif /* unix */
-
- #ifdef tos
- #define EXEC_EXTENSIONS { ".ttp", ".prg", NULL }
- #define PATHSEP ','
- #endif
-
- #if defined(OS2) || defined(__DOS__) || defined(__WINDOWS__) || defined(__WIN32__)
- #define EXEC_EXTENSIONS { ".exe", ".com", ".bat", ".cmd", NULL }
- #define PATHSEP ';'
- #endif
-
- #ifdef EXEC_EXTENSIONS
-
- static char *
- okToExec(const char *s)
- { static char *extensions[] = EXEC_EXTENSIONS;
- static char **ext;
-
- DEBUG(2, Sdprintf("Checking %s\n", s));
- for(ext = extensions; *ext; ext++)
- if ( stripostfix(s, *ext) )
- return ExistsFile(s) ? (char *)s : (char *) NULL;
-
- for(ext = extensions; *ext; ext++)
- { static char path[MAXPATHLEN];
-
- strcpy(path, s);
- strcat(path, *ext);
- if ( ExistsFile(path) )
- return path;
- }
-
- return (char *) NULL;
- }
- #endif /*EXEC_EXTENSIONS*/
-
- char *
- Which(const char *program, char *fullname)
- { char *path, *dir;
- char *e;
-
- if ( IsAbsolutePath(program) ||
- #if OS2 && EMX
- isDriveRelativePath(program) ||
- #endif /* OS2 */
- isRelativePath(program) ||
- strchr(program, '/') )
- { if ( (e = okToExec(program)) != NULL )
- { strcpy(fullname, e);
-
- return fullname;
- }
-
- return NULL;
- }
-
- #if OS2 && EMX
- if ((e = okToExec(program)) != NULL)
- {
- getcwd(fullname, MAXPATHLEN);
- strcat(fullname, "/");
- strcat(fullname, e);
- return fullname;
- }
- #endif /* OS2 */
- if ((path = getenv("PATH") ) == 0)
- path = DEFAULT_PATH;
-
- while(*path)
- { if ( *path == PATHSEP )
- { if ( (e = okToExec(program)) != NULL)
- { strcpy(fullname, e);
-
- return fullname;
- } else
- path++; /* fix by Ron Hess (hess@sco.com) */
- } else
- { char tmp[MAXPATHLEN];
-
- for(dir = fullname; *path && *path != PATHSEP; *dir++ = *path++)
- ;
- if (*path)
- path++; /* skip : */
- if (strlen(fullname) + strlen(program)+2 > MAXPATHLEN)
- continue;
- *dir++ = '/';
- *dir = EOS;
- strcpy(dir, program);
- if ( (e = okToExec(OsPath(fullname, tmp))) != NULL )
- return e;
- }
- }
-
- return NULL;
- }
-
-
- /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- void Pause(time)
- real time;
-
- Suspend execution `time' seconds. Time is given as a floating
- point, expressing the time to sleep in seconds.
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
-
- #ifdef HAVE_SELECT
-
- void
- Pause(real time)
- { struct timeval timeout;
-
- if ( time <= 0.0 )
- return;
-
- if ( time < 60.0 ) /* select() is expensive. Does it make sense */
- { timeout.tv_sec = (int) time;
- timeout.tv_usec = (int)(time * 1000000) % 1000000;
- select(32, NULL, NULL, NULL, &timeout);
- } else
- sleep( (int)(time+0.5) );
- }
-
- #else /*!HAVE_SELECT*/
- #ifdef HAVE_DOSSLEEP
-
- void /* a millisecond granualrity. */
- Pause(time) /* the EMX function sleep uses a seconds */
- real time; /* granularity only. */
- { /* the select() trick does not work at all. */
- if ( time <= 0.0 )
- return;
-
- DosSleep((ULONG)(time * 1000));
- }
-
- #else /*HAVE_DOSSLEEP*/
- #ifdef HAVE_SLEEP
-
- void
- Pause(real t)
- { if ( t <= 0.5 )
- return;
-
- sleep((int)(t + 0.5));
- }
- #else /*HAVE_SLEEP*/
- #ifdef HAVE_DELAY
-
- void
- Pause(real t)
- { delay((int)(t * 1000));
- }
-
- #endif /*HAVE_DELAY*/
- #endif /*HAVE_SLEEP*/
- #endif /*HAVE_DOSSLEEP*/
- #endif /*HAVE_SELECT*/
-
- #if tos
- void
- Pause(t)
- real t;
- { long wait = (long)(t * 200.0);
- long start_tick = clock();
- long end_tick = wait + start_tick;
-
- while( clock() < end_tick )
- { if ( kbhit() )
- { wait_ticks += clock() - start_tick;
- start_tick = clock();
- TtyAddChar(getch());
- }
- }
-
- wait_ticks += end_tick - start_tick;
- }
- #endif
-